package cn.bitkit.tools.crypto;

import cn.bitkit.base.util.StringUtil;
import cn.bitkit.tools.common.IOUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Enumeration;

/**
 * 
 * @author changbo
 *
 */
@Slf4j
public class CertUtil {

	public static final String KEY_ALGORITHM = "RSA";
	
	static{
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
    		Security.addProvider(new BouncyCastleProvider());
        }
	}

	@SneakyThrows
	public static KeyStore loadKeyStore(byte[] fileBytes, String certKey){
		ByteArrayInputStream fis = new ByteArrayInputStream(fileBytes);
		char[] keyChars = null;
		if(StringUtil.hasValue(certKey)) {
			keyChars = certKey.toCharArray();
		}
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		keyStore.load(fis, keyChars);
		IOUtil.close(fis);
		return keyStore;
	}

	@SneakyThrows
	public static String getPrivateKeyPem(byte[] fileBytes){
		// 读取整个 PEM 文件内容
		String content = new String(fileBytes);
		// 去除 PEM 文件头部、尾部和空白字符
		content = content
				.replace("-----BEGIN PRIVATE KEY-----", "")
				.replace("-----END PRIVATE KEY-----", "")
				.replaceAll("\\s", "");
		return content;
	}

	@SneakyThrows
	public static String getPrivateKey(byte[] fileBytes, String certKey){
		char[] keyChars = certKey.toCharArray();
		KeyStore keyStore = loadKeyStore(fileBytes, certKey);
		Enumeration<String> aliases = keyStore.aliases();
		String keyAlias = null;
		while (aliases.hasMoreElements()) {
			keyAlias = aliases.nextElement();
			Key key = keyStore.getKey(keyAlias, keyChars);
			if (key != null) {
				break;
			}
		}
		PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyChars);
		return StringUtil.encodeBase64(privateKey.getEncoded());
	}

	@SneakyThrows
	public static String getPublicKey(byte[] fileBytes) {
		ByteArrayInputStream is = new ByteArrayInputStream(fileBytes);
		CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
		X509Certificate x509Certificate = (X509Certificate)certificateFactory.generateCertificate(is);
		PublicKey publicKey = x509Certificate.getPublicKey();
		IOUtil.close(is);
		return StringUtil.encodeBase64(publicKey.getEncoded());
	}

	@SneakyThrows
	public static PrivateKey getEncodedPrivateKey(String base64) {
		byte[] bytes = StringUtil.decodeBase64(base64);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		return keyFactory.generatePrivate(keySpec);
	}

	@SneakyThrows
	public static PublicKey getEncodedPublicKey(String base64) {
		byte[] bytes = StringUtil.decodeBase64(base64);
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytes);
		KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
		return factory.generatePublic(x509EncodedKeySpec);
	}
	
}
